//
// $Id: ValueComputingMap.as 128 2011-04-25 07:49:53Z charlie.groves@gmail.com $
//
// aspirin library - Taking some of the pain out of Actionscript development.
// Copyright (C) 2007-2010 Three Rings Design, Inc., All Rights Reserved
// http://code.google.com/p/ooo-aspirin/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

package com.threerings.util.maps {

import com.threerings.util.Map;
import com.threerings.util.Maps;

/**
 * A Map that fills in values for missing keys using a supplied function rather than returning
 * undefined. containsKey() can still safely be used to see whether a mapping exists or not.
 */
public class ValueComputingMap extends ForwardingMap
{
    /** Creates a new ValueComputingMap that uses the given function */
    public static function newMapOf(keyClazz :Class, computer :Function) :Map
    {
        return new ValueComputingMap(Maps.newMapOf(keyClazz), computer);
    }

    /** Creates a new ValueComputing map that fills in empty arrays for missing keys. */
    public static function newArrayMapOf(keyClazz :Class) :Map
    {
        return new ValueComputingMap(Maps.newMapOf(keyClazz), function (..._) :Array { return [] });
    }

    public function ValueComputingMap (source :Map, computer :Function)
    {
        super(source);
        _computer = computer;
    }

    /** @inheritDoc */
    override public function get (key :Object) :*
    {
        var val :* = super.get(key);
        if (val === undefined) {
            val = _computer(key);
            if (val !== undefined) {
                put(key, val);
            }
        }
        return val;
    }

    /** The function used to calculate values for missing keys. @private */
    protected var _computer :Function;
}
}
